package cn.dckeji.dcssm.common.handle;

import cn.dckeji.dcssm.common.utils.IPUtil;
import cn.dckeji.dcssm.common.utils.LogUtil;
import cn.dckeji.dcssm.entity.ErrorLog;
import cn.dckeji.dcssm.service.ErrorLogService;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.setting.dialect.Props;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDateTime;

/**
 * @author kenny
 * @Title: HandlerExceptionResolver
 * @ProjectName dcssm
 * @Description: 全局异常拦截器
 * @date 2019/3/4 9:28
 */
public class GlobalExceptionHandler implements HandlerExceptionResolver {

    @Autowired
    private ErrorLogService errorLogService;

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        if (handler instanceof HandlerMethod) {
            LogUtil.logError(">>>>>>系统异常，记录异常信息到数据库------start------");
            // 远程访问IP
            String ip = IPUtil.getRemortIP(request);
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            String className = handlerMethod.getBeanType().getName();
            String methodName = handlerMethod.getMethod().getName();
            StringWriter sw = new StringWriter();
            ex.printStackTrace(new PrintWriter(sw, true));

            // 插入异常日志到数据库
            ErrorLog log = new ErrorLog();
            log.setIp(ip);
            log.setClassName(className);
            log.setMethodName(methodName);
            log.setExceptionType(ex.getClass().getSimpleName());
            log.setExceptionMsg(sw.toString()); // 异常详细信息
            log.setView(0); // 默认未读,0:为查看、1：已查看
            log.setGmtCreate(LocalDateTime.now());
            this.errorLogService.save(log);
            LogUtil.logError("服务器异常:"+ ex.getMessage(), ex);
            LogUtil.logError(">>>>>>系统异常，记录异常信息到数据库------end------");

            Props props = new Props("config/mailto.properties", "utf-8");
            boolean isOpen = props.getBool("isOpen");
            if (isOpen) {
                //发送到邮箱
                String toUserMail = props.getStr("toUserMail");
                MailUtil.send(toUserMail, "点创项目:"+request.getContextPath()+"--异常信息:<<类名:"+className+",方法名:"+methodName+">>", getExceptionDetail(ex), false);
            }

        }
        ModelAndView mv = new ModelAndView();
        /*	使用response返回	*/
        response.setStatus(500); //设置状态码
        response.setContentType(MediaType.APPLICATION_JSON_VALUE); //设置ContentType
        response.setCharacterEncoding("UTF-8"); //避免乱码
        response.setHeader("Cache-Control", "no-cache, must-revalidate");

        try {
            response.getWriter().write("{\"code\":500,\"message\":\"" + ex.getMessage() + "\"}");
        } catch (IOException e) {
            LogUtil.logError("与客户端通讯异常:"+ e.getMessage(), e);
        }
        return mv;
    }

    public String getExceptionDetail(Exception e) {
        StringBuffer stringBuffer = new StringBuffer(e.toString() + "\n");
        StackTraceElement[] messages = e.getStackTrace();
        int length = messages.length;
        for (int i = 0; i < length; i++) {
            stringBuffer.append("\t"+messages[i].toString()+"\n");
        }
        return stringBuffer.toString();
    }
}
